package com.ryskoo.customer.customer.service;

import com.ryskoo.common.constant.CustomerParamConstant;
import com.ryskoo.customer.customer.domain.CustomerPO;
import com.ryskoo.customer.customer.repository.ICustomerRepository;
import com.ryskoo.customer.customeraccount.domain.CustomerAccountPO;
import com.ryskoo.customer.customeraccount.service.ICustomerAccountService;
import com.ryskoo.customer.vendor.domain.VendorPO;
import com.ryskoo.customer.vendor.service.IVendorService;
import com.ryskoo.framework.core.bean.QueryConditionEnum;
import com.ryskoo.framework.core.bean.QueryMessageDTO;
import com.ryskoo.framework.core.exception.InvalidParamException;
import com.ryskoo.framework.core.service.BasicServiceImpl;
import com.ryskoo.framework.core.utils.MD5Util;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 会员业务基础处理
 *
 * @author huanghe
 */
@Service
@Transactional
public class CustomerServiceImpl extends BasicServiceImpl<CustomerPO> implements ICustomerService {

    @Autowired
    private ICustomerRepository customerRepository;

    @Autowired
    private ICustomerAccountService customerAccountService;

    @Autowired
    private IVendorService vendorService;

    @PostConstruct
    public void init() {
        this.setDao(customerRepository);
    }

    /**
     * 商户后台 - 新增会员
     */
    @Override
    public void platAddCustomer(CustomerPO m) {
        // 密码加密，MD5
        String password = MD5Util.md5(m.getLoginName() + m.getPassword());
        m.setPassword(password);
        // 来源：商户后台
        m.setSource(CustomerParamConstant.SOURCE_PLAT);
        // 保存会员账户表
        this.create(m);
        // 保存会员数据信息表
        CustomerAccountPO customerAccount = m.getCustomerAccount();
        if (customerAccount == null) {
            customerAccount = new CustomerAccountPO();
        }
        customerAccount.setCustomerUuid(m.getUuid());
        customerAccountService.create(customerAccount);
    }

    /**
     * 商户后台 - 编辑会员
     */
    @Override
    public void platEditCustomer(CustomerPO m) {
        CustomerPO customer = this.updateGenCustomerModel(m);
        // 如果重置了密码，则重新设置密码
        if (m.isResetPassword()) {
            // 密码加密，MD5
            String password = MD5Util.md5(m.getLoginName() + m.getPassword());
            customer.setPassword(password);
        }
        // 更新会员对象
        this.update(customer);
        // 更新会员数据信息表
        CustomerAccountPO ca = m.getCustomerAccount();
        CustomerAccountPO customerAccount = this.updateGenCustomerAccountModel(ca);
        customerAccountService.update(customerAccount);
    }

    /**
     * 商户后台 - 冻结/激活 会员
     *
     * @param idList
     * @param activeState
     * @return
     */
    @Override
    public void handleFreeze(List<String> idList, String activeState) {
        customerRepository.handleFreeze(idList, activeState);
    }

    /**
     * 商户后台 - 查询会员列表
     */
    @Override
    public List<CustomerPO> queryCustomerList(QueryMessageDTO qm) {
        return customerRepository.queryCustomerList(qm, true);
    }

    /**
     * 商户后台 - 查询会员数量（连表查询）
     */
    @Override
    public int queryCustomerCount(QueryMessageDTO qm) {
        return customerRepository.queryCustomerCount(qm);
    }

    /**
     * 查询会员的用户名/手机号/编号 是否已存在
     *
     * @param loginName
     * @return
     */
    @Override
    public boolean checkLoginNameExist(String loginName, String entityNo, String uuid) {
        return customerRepository.checkLoginNameExist(loginName, entityNo, uuid);
    }

    private CustomerPO updateGenCustomerModel(CustomerPO newModel) {
        CustomerPO oldModel = null;
        if (newModel != null) {
            oldModel = this.getByUuid(newModel.getUuid());
            oldModel.setMobile(newModel.getMobile());
            oldModel.setEntityNo(newModel.getEntityNo());
            oldModel.setActiveState(newModel.getActiveState());
        }
        return oldModel;
    }

    private CustomerAccountPO updateGenCustomerAccountModel(CustomerAccountPO newModel) {
        CustomerAccountPO oldModel = null;
        if (newModel != null) {
            oldModel = customerAccountService.getByUuid(newModel.getUuid());
            oldModel.setSex(newModel.getSex());
            oldModel.setBirthday(newModel.getBirthday());
            oldModel.setRemark(newModel.getRemark());
        }
        return oldModel;
    }

    /**
     * 平台后台 - 重置会员密码
     *
     * @param sendMessage
     * @param password
     * @param uuids
     * @return
     */
    @Override
    public void modifyPassword(boolean sendMessage, String password, List<String> uuids) {
        for (String uuid : uuids) {
            CustomerPO m = this.getByUuid(uuid);
            m.setPassword(MD5Util.md5(m.getLoginName() + password));
            this.update(m);
        }
    }

    /**
     * 微信小程序注册会员
     *
     * @param data 手机号以及openid等微信账户信息
     * @return 会员信息 {@link CustomerPO}
     * @throws InvalidParamException 数据校验异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CustomerPO wechatRegister(Map<String, Object> data) throws InvalidParamException {
        String openid = MapUtils.getString(data, "openid");
        String unionid = MapUtils.getString(data, "unionid");
        String vendorId = MapUtils.getString(data, "vendorId");
        String wxplat = MapUtils.getString(data, "wxplat");

        // 注册前校验
        checkBeforeRegister(data);
        CustomerPO customer = getByOpenidOrUnionid(vendorId, openid, wxplat, unionid);
        if (null == customer) {
            customer = new CustomerPO();
            customer.setVendorId(vendorId);
            switch (wxplat) {
                case "MP":
                    customer.setOpenid(openid);
                    break;
                case "MINI":
                    customer.setOpenidApp(openid);
                    break;
                case "OPEN":
                    customer.setOpenidOpen(openid);
                    break;
                default:
                    throw new InvalidParamException("参数错误");
            }
            customer.setUnionid(unionid);
            customer.setLoginName(MapUtils.getString(data, "nickname"));
            customer.setActiveState(CustomerParamConstant.ACTIVE_STATE_NORMAL);
            customer.setSource(MapUtils.getString(data, "source"));
            customerRepository.create(customer);
            // 保存会员账户详细信息
            CustomerAccountPO customerAccount = new CustomerAccountPO();
            customerAccount.setCustomerUuid(customer.getUuid());
            customerAccount.setNickname(MapUtils.getString(data, "nickname"));
            String headimgurl = MapUtils.getString(data, "headimgurl");
            if (StringUtils.startsWith(headimgurl, "http:")) {
                headimgurl = StringUtils.replace(headimgurl, "http:", "https:");
            }
            customerAccount.setImage(headimgurl);
            customerAccount.setSex(MapUtils.getIntValue(data, "sex"));
            customerAccountService.create(customerAccount);
            customer.setCustomerAccount(customerAccount);
        }
        return customer;
    }

    private CustomerPO getByMobile(String mobile) {
        QueryMessageDTO queryMessage = new QueryMessageDTO();
        queryMessage.addCondition("mobile", QueryConditionEnum.EQ.name(), mobile);
        List<CustomerPO> list = customerRepository.queryByCondition(queryMessage, false);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据微信openid或者unionid查询会员
     * 当unionid不为空时，优先已unionid为条件查询
     * @param vendorId  商户id
     * @param openid  微信openid
     * @param wxplat  微信平台 MP:公众号, APP: 小程序, OPEN:开放平台
     * @param unionid 微信unionid
     * @return 会员信息 {@link CustomerPO}
     */
    @Override
    public CustomerPO getByOpenidOrUnionid(String vendorId, String openid, String wxplat, String unionid) {
        QueryMessageDTO queryMessage = new QueryMessageDTO();
        queryMessage.addCondition("vendorId", QueryConditionEnum.EQ.name(), vendorId);
        if (StringUtils.isNotBlank(unionid)) {
            queryMessage.addCondition("unionid", QueryConditionEnum.EQ.name(), unionid);
        } else {
            switch (wxplat) {
                case "MP":
                    queryMessage.addCondition("openid", QueryConditionEnum.EQ.name(), openid);
                    break;
                case "MINI":
                    queryMessage.addCondition("openidApp", QueryConditionEnum.EQ.name(), openid);
                    break;
                case "OPEN":
                    queryMessage.addCondition("openidOpen", QueryConditionEnum.EQ.name(), openid);
                    break;
                default:
                    throw new InvalidParamException("参数错误");
            }

        }
        List<CustomerPO> list = customerRepository.queryByCondition(queryMessage, false);
        if (null != list && list.size() > 0) {
            CustomerPO customer = list.get(0);
            if (null != customer) {
                customer.setCustomerAccount(customerAccountService.getByCustomerUuid(customer.getUuid()));

            }
            return customer;
        }
        return null;
    }

    @Override
    public void updateCustomerOpenid(CustomerPO customer, String wxplat, String openid) {
        // 如果会员存在，但是会员当前所在的微信平台openid为空，则同时保存当前平台的openid
        if ("MP".equals(wxplat) && StringUtils.isBlank(customer.getOpenid())) {
            customer.setOpenid(openid);
            customerRepository.update(customer);
        } else if ("MINI".equals(wxplat) && StringUtils.isBlank(customer.getOpenidApp())) {
            customer.setOpenidApp(openid);
            customerRepository.update(customer);
        } else if ("OPEN".equals(wxplat) && StringUtils.isBlank(customer.getOpenidOpen())) {
            customer.setOpenidOpen(openid);
            customerRepository.update(customer);
        }
    }

    /**
     * 根据商户id查询商户的会员
     *
     * @param queryMessage 统一查询条件 {@link QueryMessageDTO}
     * @return 信息列表 {@link List}&lt;{@link Map}&lt;{@link String}, {@link Object}&gt&gt;
     */
    @Override
    public List<Map<String, Object>> getCustomerByVendorId(QueryMessageDTO queryMessage) {
        return customerRepository.queryCustomerByVendorId(queryMessage, true);
    }

    /**
     * 根据商户id查询商户的会员的总数
     *
     * @param queryMessage 统一查询条件 {@link QueryMessageDTO}
     * @return 商户的会员总数
     */
    @Override
    public int getCustomerCountByVendorId(QueryMessageDTO queryMessage) {
        return customerRepository.getCustomerCountByVendorId(queryMessage);
    }

    /**
     * 更新会员手机号
     *
     * @param customerId 会员id
     * @param mobile     手机号
     * @return 会员信息 {@link CustomerPO}
     */
    @Override
    public CustomerPO updateMobile(String customerId, String mobile) {
        CustomerPO customer = customerRepository.getByUuid(customerId);
        if (null == customer) {
            throw new InvalidParamException("会员不存在");
        }
        // 检查手机号
        checkMobile(mobile, true, customer.getUuid());
        customer.setMobile(mobile);
        customerRepository.update(customer);
        customer.setCustomerAccount(customerAccountService.getByCustomerUuid(customer.getUuid()));
        return customer;
    }

    private void checkBeforeRegister(Map<String, Object> data) throws InvalidParamException {
        // 校验微信openid
        checkOpenid(MapUtils.getString(data, "openid"));
        // 校验商户id
        checkVendorId(MapUtils.getString(data, "vendorId"));
    }

    private void checkOpenid(String openid) throws InvalidParamException {
        if (StringUtils.isBlank(openid)) {
            throw new InvalidParamException("微信 openid 为空");
        }
    }

    private void checkMobile(String mobile, boolean isUpdate, String uuid) throws InvalidParamException {
        if (StringUtils.isBlank(mobile)) {
            throw new InvalidParamException("手机号为空");
        }
        if (!mobile.matches("^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$")) {
            throw new InvalidParamException("手机号错误");
        }
        QueryMessageDTO queryMessage = new QueryMessageDTO();
        queryMessage.addCondition("mobile", QueryConditionEnum.EQ.name(), mobile);
        if (isUpdate) {
            queryMessage.addCondition("uuid", QueryConditionEnum.NE.name(), uuid);
        }
        List<CustomerPO> customerList = customerRepository.queryCustomerList(queryMessage, false);
        if (null != customerList && !customerList.isEmpty()) {
            throw new InvalidParamException("手机号已存在");
        }
    }

    private void checkVendorId(String vendorId) throws InvalidParamException {
        if (StringUtils.isBlank(vendorId)) {
            throw new InvalidParamException("商户id为空");
        }
        VendorPO vendor = vendorService.getByUuid(vendorId);
        if (null == vendor) {
            throw new InvalidParamException("商户不存在");
        }
    }


    /**
     * 根据时间统计商户的会员数
     *
     * @param date
     * @param vendorUuid
     * @return
     */
    @Override
    public int getCustomerCountByDate(String date, String vendorUuid) {
        return customerRepository.getCustomerCountByDate(date, vendorUuid);
    }

    @Override
    public CustomerPO getCustomerInfo(String uuid){
        CustomerPO customerPO = customerRepository.getByUuid(uuid);
        if(null==customerPO){
            throw new InvalidParamException("会员不存在");
        }
        CustomerAccountPO accountPO = customerAccountService.getByCustomerUuid(uuid);
        customerPO.setCustomerAccount(accountPO);
        if(StringUtils.isNotEmpty(customerPO.getInviterUuid())){
            CustomerAccountPO inviter = customerAccountService.getByCustomerUuid(customerPO.getInviterUuid());
            Optional<CustomerAccountPO> inviterAccount = Optional.ofNullable(inviter);
            inviterAccount.ifPresent(x->customerPO.setInviterName(x.getNickname()));
        }
        return customerPO;
    }

    @Override
    public void setRemark(String uuid, String remark) {
        CustomerPO customerPO = customerRepository.getByUuid(uuid);
        if(null==customerPO){
            throw new InvalidParamException("会员不存在");
        }
        CustomerAccountPO accountPO = customerAccountService.getByCustomerUuid(uuid);
        accountPO.setRemark(remark);
        customerAccountService.update(accountPO);
    }
}
